package com.ruoyi.back.v2.service

import cn.hutool.core.date.DateUtil
import cn.hutool.core.util.NumberUtil
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.ruoyi.app.common.Data
import com.ruoyi.app.common.Ok
import com.ruoyi.app.common.id
import com.ruoyi.back.domain.UserMemberOrder
import com.ruoyi.back.enums.PayStatusEnum
import com.ruoyi.back.mapper.*
import com.ruoyi.back.service.AppUserService
import com.ruoyi.back.service.UserMemberOrderService
import com.ruoyi.back.v2.domain.*
import com.ruoyi.exception.FlyException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional


@Service
class PromoteRelationshipService : ServiceImpl<PromoteRelationshipMapper, PromoteRelationship>() {

    /**
     * 获取指定用户的上级用户
     */
    fun firstLevelUser(userId: Long?): Long? = userPromoteRelationShip(userId)?.firstLevel

    /**
     * 获取指定用户的推广关系
     */
    fun userPromoteRelationShip(userId: Long?): PromoteRelationship? = getOne(
        KtQueryWrapper(PromoteRelationship::class.java)
            .eq(PromoteRelationship::userId, userId)
    )
}

@Service
class InviteDetailService : ServiceImpl<InviteDetailMapper, InviteDetail>() {

    @Autowired
    private lateinit var userMemberOrderService: UserMemberOrderService


    fun inviteFreeTaskUser(bindUserRelationParam: BindUserRelationParam): Boolean =
        save(InviteDetail().apply {
            userId = bindUserRelationParam.inviteUserId
            inviteUserId = bindUserRelationParam.userId
            inviteType = 0
            DateUtil.date().let {
                year = DateUtil.year(it)
                month = DateUtil.month(it)
                day = DateUtil.dayOfMonth(it)
                createTime = it
            }
        })


    fun haveInviteFreeTaskUserNum(userId: Long): Int =
        count(KtQueryWrapper(InviteDetail::class.java)
            .eq(InviteDetail::userId, userId)
            .eq(InviteDetail::inviteType, 0)
            .eq(InviteDetail::inviteUseStatus, false))


    fun resetInviteFreeTask(userId: Long) {
        list(KtQueryWrapper(InviteDetail::class.java)
            .eq(InviteDetail::userId, userId)
            .eq(InviteDetail::inviteType, 0)
            .eq(InviteDetail::inviteUseStatus, false))
            .takeIf { it.isNotEmpty() }
            ?.forEach {
                updateById(it.apply {
                    inviteUseStatus = true
                })
            }
    }


    /**
     * 消费笔数以及金额
     */
    fun consumerTotalNumAndMoney(type: Int?, today: Boolean? = false): Pair<Int, Double> =
        inviteUserNum(type, today)
            .takeIf { it.isNotEmpty() }
            ?.let { userIds ->
                userMemberOrderService.list(
                    KtQueryWrapper(UserMemberOrder::class.java)
                        .eq(UserMemberOrder::payStatus, PayStatusEnum.PAY_SUCCESS.code)
                        .`in`(UserMemberOrder::createBy, userIds)
                )
                    .let { userMemberOrders ->
                        userMemberOrders.size to userMemberOrders.sumOf { it.payAmount ?: 0.0 }
                    }
            }
            ?: (0 to 0.0)

    /**
     * 用户消费金额
     */
    fun consumerMoney(userId: Long): Double =
        userMemberOrderService.list(KtQueryWrapper(UserMemberOrder::class.java)
            .eq(UserMemberOrder::createBy, userId)
            .eq(UserMemberOrder::payStatus, PayStatusEnum.PAY_SUCCESS.code))
            .takeIf { it.isNotEmpty() }
            ?.sumOf { it.payAmount ?: 0.0 }
            ?: 0.0

    fun inviteUserPage(type: Int?, pageNum: Int, pageSize: Int, userId: Long): Page<InviteDetail> =
        page(
            Page(pageNum.toLong(), pageSize.toLong()), KtQueryWrapper(InviteDetail::class.java)
                .eq(type != null, InviteDetail::inviteLevel, type)
                .eq(InviteDetail::inviteType, 1)
                .eq(InviteDetail::userId, userId)
                .orderByDesc(InviteDetail::createTime)
        )

    fun userInviteUserNum(userId: Long): Int =
        count(KtQueryWrapper(InviteDetail::class.java)
            .eq(InviteDetail::userId, userId)
            .eq(InviteDetail::inviteType, 1))


    /**
     * 获取已邀请的用户id
     */
    fun inviteUserNum(type: Int?, today: Boolean? = false) = when (today) {
        true -> DateUtil.date().run {
            list(
                KtQueryWrapper(InviteDetail::class.java)
                    .select(InviteDetail::inviteUserId)
                    .eq(InviteDetail::userId, id())
                    .eq(type != null, InviteDetail::inviteLevel, type)
                    .eq(InviteDetail::year, DateUtil.year(this))
                    .eq(InviteDetail::month, DateUtil.month(this))
                    .eq(InviteDetail::day, DateUtil.dayOfMonth(this))
                    .eq(InviteDetail::inviteType, 1)
            )
                .takeIf { it.isNotEmpty() }
                ?.map { it.inviteUserId }
                ?: emptyList()
        }

        false -> list(
            KtQueryWrapper(InviteDetail::class.java)
                .select(InviteDetail::inviteUserId)
                .eq(InviteDetail::userId, id())
                .eq(type != null, InviteDetail::inviteLevel, type)
                .eq(InviteDetail::inviteType, 1)
        )
            .takeIf { it.isNotEmpty() }
            ?.map { it.inviteUserId }
            ?: emptyList()

        null -> emptyList()
    }
}

@Service
class WithdrawalsDetailService : ServiceImpl<WithdrawalsDetailMapper, WithdrawalsDetail>() {

    /**
     * 获取用户已提现金额
     */
    fun withdrawMoney(): Double = list(
        KtQueryWrapper(WithdrawalsDetail::class.java)
            .eq(WithdrawalsDetail::userId, id())
            .eq(WithdrawalsDetail::checkStatus, 1)
    )
        .takeIf { it.isNotEmpty() }
        ?.sumOf { it.money ?: 0.0 }
        ?: 0.0

    /**
     * 获取用户已提现金额
     */
    fun withdrawMoney(userId: Long): Double = list(
        KtQueryWrapper(WithdrawalsDetail::class.java)
            .eq(WithdrawalsDetail::userId, userId)
            .eq(WithdrawalsDetail::checkStatus, 1)
    )
        .takeIf { it.isNotEmpty() }
        ?.sumOf { it.money ?: 0.0 }
        ?: 0.0

    fun withdrawPage(pageNum: Int, pageSize: Int, userId: Long): Page<WithdrawalsDetail> =
        page(Page(pageNum.toLong(), pageSize.toLong()), KtQueryWrapper(WithdrawalsDetail::class.java)
            .eq(WithdrawalsDetail::userId, userId)
            .orderByDesc(WithdrawalsDetail::createTime))

    /**
     * 获取用户待审核数据
     */
    fun withdrawPreCheck(userId: Long): WithdrawalsDetail? =
        getOne(KtQueryWrapper(WithdrawalsDetail::class.java)
            .eq(WithdrawalsDetail::userId, userId)
            .eq(WithdrawalsDetail::checkStatus, 0)
            .last("limit 1"))
}

@Service
class EmployeeDetailService : ServiceImpl<EmployeeDetailMapper, EmployeeDetail>() {


    /**
     * 获取收益分页
     */
    fun employeePage(pageNum: Int, pageSize: Int, userId: Long): Page<EmployeeDetail> =
        page(Page(pageNum.toLong(), pageSize.toLong()),KtQueryWrapper(EmployeeDetail::class.java)
            .eq(EmployeeDetail::userId, userId)
            .orderByDesc(EmployeeDetail::createTime))

    fun employeeMoney(userId: Long): Double =
        list(KtQueryWrapper(EmployeeDetail::class.java)
            .eq(EmployeeDetail::userId, userId)
            .eq(EmployeeDetail::employeeType, 1))
            .takeIf { it.isNotEmpty() }
            ?.sumOf { it.employeeMoney ?: 0.0 }
            ?: 0.0

    /**
     * 累计收益
     */
    fun totalEmployee(type: Int?, today: Boolean? = false): Double = when (today) {
        true -> DateUtil.date().run {
            list(
                KtQueryWrapper(EmployeeDetail::class.java)
                    .eq(EmployeeDetail::userId, id())
                    .eq(type != null, EmployeeDetail::employeeLevel, type)
                    .eq(EmployeeDetail::employeeType, 1)
                    .eq(InviteDetail::year, DateUtil.year(this))
                    .eq(InviteDetail::month, DateUtil.month(this))
                    .eq(InviteDetail::day, DateUtil.dayOfMonth(this))
            )
                .takeIf { it.isNotEmpty() }
                ?.sumOf { it.employeeMoney ?: 0.0 }
                ?: 0.0
        }

        false -> list(
            KtQueryWrapper(EmployeeDetail::class.java)
                .eq(EmployeeDetail::userId, id())
                .eq(type != null, EmployeeDetail::employeeLevel, type)
                .eq(EmployeeDetail::employeeType, 1)
        )
            .takeIf { it.isNotEmpty() }
            ?.sumOf { it.employeeMoney ?: 0.0 }
            ?: 0.0

        null -> 0.0
    }
}

@Service
@Transactional
class SpreadSettingService : ServiceImpl<SpreadSettingMapper, SpreadSetting>() {

    /**
     * 保存推广设置
     */
    fun saveSpreadSetting(spreadSetting: SpreadSetting) = saveOrUpdate(spreadSetting)


    /**
     * 获取推广设置
     */
    fun getSpreadSetting(): SpreadSetting =
        getOne(KtQueryWrapper(SpreadSetting::class.java).last("limit 1")) ?: SpreadSetting()

    /**
     * 获取收益
     */
    fun getEmployee(money: Double): Pair<Double, Double> =
        (getSpreadSetting().firstReturnCommission?.div(100)?.times(money)
            ?: 0.0).two() to (getSpreadSetting().secondReturnCommission?.div(100)?.times(money) ?: 0.0).two()
}

fun Double.two() = NumberUtil.round(this, 2).toDouble()

@Service
class SpreadManageService {

    @Autowired
    private lateinit var promoteRelationshipService: PromoteRelationshipService

    @Autowired
    private lateinit var inviteDetailService: InviteDetailService

    @Autowired
    private lateinit var withdrawalsDetailService: WithdrawalsDetailService

    @Autowired
    private lateinit var employeeDetailService: EmployeeDetailService

    @Autowired
    private lateinit var spreadSettingService: SpreadSettingService

    @Autowired
    private lateinit var appUserService: AppUserService


    /**
     * 绑定用户关系
     */
    fun bindUserRelation(bindUserRelationParam: BindUserRelationParam): Boolean {

        //绑定推广关系
        //1. 如果该用户已经绑定过上下级关系则不能重复绑定
        return promoteRelationshipService.userPromoteRelationShip(bindUserRelationParam.userId)
            ?.run { false }
            ?: run {

                //2. 没有绑定 则开始绑定推广关系
                val promoteRelationship = PromoteRelationship()
                if (promoteRelationshipService.save(promoteRelationship.apply {
                        userId = bindUserRelationParam.userId
                        firstLevel = bindUserRelationParam.inviteUserId
                        secondLevel = promoteRelationshipService.firstLevelUser(bindUserRelationParam.inviteUserId)
                    })) {

                    //3. 绑定成功则绑定邀请人的邀请明细
                    //3.1 绑定一级邀请人的邀请明细
                    promoteRelationship.firstLevel?.let { firstLevel ->
                        inviteDetailService.save(InviteDetail().apply {
                            userId = firstLevel
                            appUserService.getById(promoteRelationship.userId).let {
                                inviteUserId = it.id
                                inviteUserIdStr = it.userId
                                inviteUserName = it.username
                            }

                            inviteLevel = 1
                            inviteType = 1

                            DateUtil.date().let {
                                year = DateUtil.year(it)
                                month = DateUtil.month(it)
                                day = DateUtil.dayOfMonth(it)
                                createTime = it
                            }

                        })
                    }

                    //3.2 绑定二级邀请人的邀请明细
                    promoteRelationship.secondLevel?.let { secondLevel ->
                        inviteDetailService.save(InviteDetail().apply {
                            userId = secondLevel
                            appUserService.getById(promoteRelationship.userId).let {
                                inviteUserId = it.id
                                inviteUserIdStr = it.userId
                                inviteUserName = it.username
                            }
                            inviteLevel = 2
                            inviteType = 1

                            DateUtil.date().let {
                                year = DateUtil.year(it)
                                month = DateUtil.month(it)
                                day = DateUtil.dayOfMonth(it)
                                createTime = it
                            }

                        })
                    }

                    return true
                } else false
            }


    }

    fun bindEmployeeRelation(bindEmployeeRelationParam: BindEmployeeRelationParam) {


        promoteRelationshipService.userPromoteRelationShip(bindEmployeeRelationParam.userId)
            ?.let { promoteRelationship ->

                val employee = spreadSettingService.getEmployee(bindEmployeeRelationParam.payAmount ?: 0.0)

                val providerDescDetail = bindEmployeeRelationParam.payProgramType?.let {
                    when (it) {
                        1 -> "${appUserService.appUserInfo(bindEmployeeRelationParam.userId!!)?.username ?: "未知"}-购买会员￥${bindEmployeeRelationParam.payAmount}"
                        2 -> "${appUserService.appUserInfo(bindEmployeeRelationParam.userId!!)?.username ?: "未知"}-单次收费${bindEmployeeRelationParam.payAmount}"
                        else -> "下级退款"
                    }
                }
                // 一级
                promoteRelationship.firstLevel?.let { firstLevel ->

                    //1. 增加推广关系收益
                    promoteRelationshipService.userPromoteRelationShip(firstLevel)?.let {
                        promoteRelationshipService.updateById(it.apply {
                            employeeMoney = (employeeMoney ?: 0.0).plus(employee.first)
                        })
                    }

                    //2. 增加收益明细
                    employeeDetailService.save(EmployeeDetail().apply {
                        userId = firstLevel
                        providerUserId = bindEmployeeRelationParam.userId
                        employeeLevel = 1
                        providerDesc = providerDescDetail
                        employeeMoney = employee.first
                        employeeType = providerDesc?.run { 1 } ?: 2
                        DateUtil.date().let {
                            year = DateUtil.year(it)
                            month = DateUtil.month(it)
                            day = DateUtil.dayOfMonth(it)
                            createTime = it
                        }
                    })

                }

                // 二级
                promoteRelationship.secondLevel?.let { secondeLevel ->

                    //1. 增加推广关系收益
                    promoteRelationshipService.userPromoteRelationShip(secondeLevel)?.let {
                        promoteRelationshipService.updateById(it.apply {
                            employeeMoney = (employeeMoney ?: 0.0).plus(employee.second)
                        })
                    }

                    //2. 增加收益明细
                    employeeDetailService.save(EmployeeDetail().apply {
                        userId = secondeLevel
                        providerUserId = bindEmployeeRelationParam.userId
                        employeeLevel = 2
                        providerDesc = providerDescDetail
                        employeeMoney = employee.second
                        employeeType = providerDesc?.run { 1 } ?: 2
                        DateUtil.date().let {
                            year = DateUtil.year(it)
                            month = DateUtil.month(it)
                            day = DateUtil.dayOfMonth(it)
                            createTime = it
                        }
                    })

                }


            }
    }

    fun bindWithdraw(withdrawRelationParam: WithdrawRelationParam): Data<Boolean> =
        spreadSettingService.getSpreadSetting().let { spreadSetting ->

            if ((withdrawRelationParam.money
                    ?: 0.0) < spreadSetting.withdrawMinMoney!!
            ) throw FlyException("提现金额不能小于${spreadSetting.withdrawMinMoney}")
            if ((withdrawRelationParam.money
                    ?: 0.0) > spreadSetting.withdrawMinMoney!!
            ) throw FlyException("提现金额不能大于${spreadSetting.withdrawMaxMoney}")

            withdrawalsDetailService.withdrawPreCheck(id())?.run {
                throw FlyException("已有待审核提现数据 请耐心等待!")
            }?: run {
                Ok("申请提现成功", withdrawalsDetailService.save(WithdrawalsDetail().apply {

                    appUserService.getById(id()).let {
                        userId = it.id
                        userIdStr = it.userId
                        username = it.username
                    }
                    money = withdrawRelationParam.money
                    withdrawType = withdrawRelationParam.withdrawType
                }))
            }
        }
}










